package com.thoughtworks.jsstaticanalysis;

import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.junit.Test;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;

import static junit.framework.Assert.assertEquals;

public class JavascriptParserTest {

    @Test
    public void should_find_functions() throws IOException, RecognitionException {
        String jsFile = "monthdecl.js";
        List<FoundFunction> functions = functionsInSource(jsFile);

        assertEquals(2, functions.size());
        assertFunction(functions.get(0), "anonymous", jsFile, 3, 17);
        assertScore(functions.get(0), 0);
        assertFunction(functions.get(1), "Month", jsFile, 28, 7);
        assertScore(functions.get(1), 5.5);
    }

    @Test
    public void should_find_functions2() throws RecognitionException, IOException {
        String jsFile = "monthbody.js";
        List<FoundFunction> functions = functionsInSource(jsFile);

        assertEquals(11, functions.size());
        assertFunction(functions.get(0), "anonymous", jsFile, 3, 7);
        assertFunction(functions.get(1), "anonymous", jsFile, 6, 5);
        assertFunction(functions.get(2), "getActivitySummary", jsFile, 10, 3);
        assertFunction(functions.get(3), "anonymous", jsFile, 1, 18);
        assertFunction(functions.get(4), "anonymous", jsFile, 1, 19);
        assertFunction(functions.get(5), "anonymous", jsFile, 6, 16);
        assertFunction(functions.get(6), "getLocationSummary", jsFile, 10, 14);
        assertFunction(functions.get(7), "getTravelSteps", jsFile, 3, 25);
        assertFunction(functions.get(8), "_createDayIndex", jsFile, 7, 29);
        assertFunction(functions.get(9), "_createMonth", jsFile, 9, 37);
        assertFunction(functions.get(10), "_createDayForRange", jsFile, 10, 47);
    }

    public void assertFunction(FoundFunction function, String functionName, String jsFile, int lineCount, int startLine) {
        assertEquals(functionName, function.funcName);
        assertEquals(jsFile, function.fileName);
        assertEquals(lineCount, function.lineCount);
        assertEquals(startLine, function.startLine);
    }

    public void assertScore(FoundFunction function, double score) {
        assertEquals(score, function.score);
    }

    public List<FoundFunction> functionsInSource(String jsFile) throws IOException, RecognitionException {
        ANTLRInputStream stream = new ANTLRInputStream(new FileInputStream("testJs/" + jsFile));
        JavascriptLexer lexer = new JavascriptLexer(stream);
        CommonTokenStream commonToken = new CommonTokenStream(lexer);
        JavascriptParser parser = new JavascriptParser(commonToken);
        parser.fileName = jsFile;
        parser.program();
        return parser.getFunctions();
    }

}
